package fei.zhou.service8081.business.config;

import com.github.kristofa.brave.Brave;
import com.github.kristofa.brave.Brave.Builder;
import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler;
import com.github.kristofa.brave.Sampler;
import com.github.kristofa.brave.SpanCollector;
import com.github.kristofa.brave.http.DefaultSpanNameProvider;
import com.github.kristofa.brave.http.HttpSpanCollector;
import com.github.kristofa.brave.http.HttpSpanCollector.Config;
import com.github.kristofa.brave.okhttp.BraveOkHttpRequestResponseInterceptor;
import com.github.kristofa.brave.servlet.BraveServletFilter;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 *
 * 配置Span收集器 设置收集器的详细参数，包含超时时间、上传span间隔、以及配置采集率等，进而对收集器进行初始化。
 * 
 * @author <a href="mailto:zhoufei@smartdot.com">周飞</a>
 * @since 2021/8/22 15:47
 */
@Configuration
public class SpanCollectorConfig {
    // zipkin的url地址
    @Value("${zipkin.url}")
    private String url;
    // 发给zipkin的服务器名称
    @Value("${zipkin.serviceName}")
    private String serviceName;
    
    // 连接超时时间
    @Value("${zipkin.connectTimeout}")
    private int connecTimeout;
    
    // 是否启动压缩
    @Value("${zipkin.compressionEnabled}")
    private boolean compressionEnabled;
    
    // 上传 span 的间隔时间
    @Value("${zipkin.flushInterval}")
    private int flushInterval;
    
    // 读取超时时间
    @Value("${zipkin.readTimeout}")
    private int readTimeout;
    // 采样率，默认为0.1，值越大收集越及时，但性能影响也越大
    @Value("${zipkin.samplerRate}")
    private float samplerRate;
    
    /**
     * 配置 span 收集器
     * 
     * @return
     */
    @Bean
    public SpanCollector spanCollector() {
        Config config = Config.builder()
                //连接超时时间
                .connectTimeout(connecTimeout)
                //是否启动压缩
                .compressionEnabled(compressionEnabled)
                //上传 span 的间隔时间
                .flushInterval(flushInterval)
                //读取超时时间
                .readTimeout(readTimeout).build();
                //url:zipkin的url地址
        return HttpSpanCollector.create(url, config, new EmptySpanCollectorMetricsHandler());
    }
    
    /**
     * 配置采集率
     * 作为各调用链路，只需要负责将指定格式的数据发送给zipkin
     * @param spanCollector
     * @return
     */
    @Bean
    public Brave brave(SpanCollector spanCollector) {
        //被采集的服务名称
        Builder builder = new Builder(serviceName);
        //采集器
        builder.spanCollector(spanCollector)
                //采样率，默认为0.1，值越大收集越及时，但性能影响也越大
                .traceSampler(Sampler.create(samplerRate)).build();
        return builder.build();
    }
    
    /**
     * @Description: 设置server的（服务端收到请求和服务端完成处理，并将结果发送给客户端）过滤器
     * @Param:
     * @return: 过滤器
     */
    @Bean
    public BraveServletFilter braveServletFilter(Brave brave) {
        BraveServletFilter filter = new BraveServletFilter(brave.serverRequestInterceptor(),
                brave.serverResponseInterceptor(), new DefaultSpanNameProvider());
        return filter;
    }
    
    /**
     * @Description: 设置client的 rs（表示服务端收到请求）和cs（表示客户端发起请求）的拦截器
     * @Param:
     * @return: OkHttpClient 返回请求实例
     */
    @Bean
    public OkHttpClient okHttpClient(Brave brave) {
        OkHttpClient httpClient = new OkHttpClient.Builder()
                .addInterceptor(new BraveOkHttpRequestResponseInterceptor(brave.clientRequestInterceptor(),
                        brave.clientResponseInterceptor(), new DefaultSpanNameProvider()))
                .build();
        return httpClient;
    }
}